home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / machine / irobot.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  27KB  |  1,044 lines

  1. /***************************************************************************
  2.  
  3.   machine.c
  4.  
  5.   Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
  6.   I/O ports)
  7.  
  8. ***************************************************************************/
  9.  
  10. #include "driver.h"
  11. #include "cpuintrf.h"
  12. #include "cpu/m6809/m6809.h"
  13.  
  14. /* Note:
  15.  * There's probably something wrong with the way the Mathbox gets started.
  16.  * Try compiling with IR_TIMING=1, run with logging on and take a look at
  17.  * the resulting logilfe.
  18.  * The mathbox is started in short intervals (<10 scanlines) without (!)
  19.  * checking its idle status.
  20.  * It also seems that the mathbox in this emulation would have to cope with
  21.  * approx. 5000 instructions per scanline [look at the number of instructions
  22.  * and the number of scanlines to the next mathbox start]. This seems a bit
  23.  * too high.
  24.  */
  25.  
  26. #define IR_TIMING                 1        /* try to emulate MB and VG running time */
  27. #define DISASSEMBLE_MB_ROM        0        /* generate a disassembly of the mathbox ROMs */
  28.  
  29. #define IR_CPU_STATE \
  30.     logerror(\
  31.             "pc: %4x, scanline: %d\n", cpu_getpreviouspc(), cpu_getscanline())
  32.  
  33.  
  34. UINT8 irvg_clear;
  35. static UINT8 irvg_vblank;
  36. static UINT8 irvg_running;
  37. static UINT8 irmb_running;
  38. static void *irscanline_timer;
  39.  
  40. #if IR_TIMING
  41. static void *irvg_timer;
  42. static void *irmb_timer;
  43. #endif
  44. extern void run_video(void);
  45.  
  46. extern void irobot_poly_clear(void);
  47.  
  48. extern struct osd_bitmap *polybitmapt;
  49.  
  50. static UINT8 *comRAM[2], *mbRAM, *mbROM;
  51. static UINT8 irobot_control_num = 0;
  52. static UINT8 irobot_statwr;
  53. static UINT8 irobot_out0;
  54. static UINT8 irobot_outx,irobot_mpage;
  55.  
  56. static UINT8 *irobot_combase_mb;
  57. UINT8 *irobot_combase;
  58. UINT8 irobot_bufsel;
  59. UINT8 irobot_alphamap;
  60.  
  61. static void irmb_run(void);
  62.  
  63.  
  64. /* mathbox and vector data is stored in big-endian format */
  65. #ifdef LSB_FIRST
  66. #define BYTE_XOR_LE(x)    ((x) ^ 1)
  67. #else
  68. #define BYTE_XOR_LE(x)    (x)
  69. #endif
  70.  
  71.  
  72. /***********************************************************************/
  73.  
  74.  
  75.  
  76. READ_HANDLER( irobot_sharedmem_r )
  77. {
  78.     if (irobot_outx == 3)
  79.         return mbRAM[BYTE_XOR_LE(offset)];
  80.  
  81.     if (irobot_outx == 2)
  82.         return irobot_combase[BYTE_XOR_LE(offset & 0xFFF)];
  83.  
  84.     if (irobot_outx == 0)
  85.         return mbROM[((irobot_mpage & 1) << 13) + BYTE_XOR_LE(offset)];
  86.  
  87.     if (irobot_outx == 1)
  88.         return mbROM[0x4000 + ((irobot_mpage & 3) << 13) + BYTE_XOR_LE(offset)];
  89.  
  90.     return 0xFF;
  91. }
  92.  
  93. /* Comment out the mbRAM =, comRAM2 = or comRAM1 = and it will start working */
  94. WRITE_HANDLER( irobot_sharedmem_w )
  95. {
  96.     if (irobot_outx == 3)
  97.         mbRAM[BYTE_XOR_LE(offset)] = data;
  98.  
  99.     if (irobot_outx == 2)
  100.         irobot_combase[BYTE_XOR_LE(offset & 0xFFF)] = data;
  101. }
  102.  
  103. static void irvg_done_callback (int param)
  104. {
  105.     logerror("vg done. ");
  106.     IR_CPU_STATE;
  107.     irvg_running = 0;
  108. }
  109.  
  110. WRITE_HANDLER( irobot_statwr_w )
  111. {
  112.     logerror("write %2x ", data);
  113.     IR_CPU_STATE;
  114.  
  115.     irobot_combase = comRAM[data >> 7];
  116.     irobot_combase_mb = comRAM[(data >> 7) ^ 1];
  117.     irobot_bufsel = data & 0x02;
  118.     if (((data & 0x01) == 0x01) && (irvg_clear == 0))
  119.         irobot_poly_clear();
  120.  
  121.     irvg_clear = data & 0x01;
  122.  
  123.     if ((data & 0x04) && !(irobot_statwr & 0x04))
  124.     {
  125.         run_video();
  126. #if IR_TIMING
  127.         if (irvg_running == 0)
  128.         {
  129.             logerror("vg start ");
  130.             IR_CPU_STATE;
  131.             irvg_timer = timer_set (TIME_IN_MSEC(10), 0, irvg_done_callback);
  132.         }
  133.         else
  134.         {
  135.             logerror("vg start [busy!] ");
  136.             IR_CPU_STATE;
  137.             timer_reset (irvg_timer , TIME_IN_MSEC(10));
  138.         }
  139. #endif
  140.         irvg_running=1;
  141.     }
  142.     if ((data & 0x10) && !(irobot_statwr & 0x10))
  143.         irmb_run();
  144.     irobot_statwr = data;
  145. }
  146.  
  147. WRITE_HANDLER( irobot_out0_w )
  148. {
  149.     UINT8 *RAM = memory_region(REGION_CPU1);
  150.  
  151.     irobot_out0 = data;
  152.     switch (data & 0x60)
  153.     {
  154.         case 0:
  155.             cpu_setbank(2, &RAM[0x1C000]);
  156.             break;
  157.         case 0x20:
  158.             cpu_setbank(2, &RAM[0x1C800]);
  159.             break;
  160.         case 0x40:
  161.             cpu_setbank(2, &RAM[0x1D000]);
  162.             break;
  163.     }
  164.     irobot_outx = (data & 0x18) >> 3;
  165.     irobot_mpage = (data & 0x06) >> 1;
  166.     irobot_alphamap = (data & 0x80);
  167. }
  168.  
  169. WRITE_HANDLER( irobot_rom_banksel_w )
  170. {
  171.     UINT8 *RAM = memory_region(REGION_CPU1);
  172.  
  173.     switch ((data & 0x0E) >> 1)
  174.     {
  175.         case 0:
  176.             cpu_setbank(1, &RAM[0x10000]);
  177.             break;
  178.         case 1:
  179.             cpu_setbank(1, &RAM[0x12000]);
  180.             break;
  181.         case 2:
  182.             cpu_setbank(1, &RAM[0x14000]);
  183.             break;
  184.         case 3:
  185.             cpu_setbank(1, &RAM[0x16000]);
  186.             break;
  187.         case 4:
  188.             cpu_setbank(1, &RAM[0x18000]);
  189.             break;
  190.         case 5:
  191.             cpu_setbank(1, &RAM[0x1A000]);
  192.             break;
  193.     }
  194.     osd_led_w(0,data & 0x10);
  195.     osd_led_w(1,data & 0x20);
  196. }
  197.  
  198. static void scanline_callback(int scanline)
  199. {
  200.     if (scanline == 0) irvg_vblank=0;
  201.     if (scanline == 224) irvg_vblank=1;
  202.     logerror("SCANLINE CALLBACK %d\n",scanline);
  203.     /* set the IRQ line state based on the 32V line state */
  204.     cpu_set_irq_line(0, M6809_IRQ_LINE, (scanline & 32) ? ASSERT_LINE : CLEAR_LINE);
  205.  
  206.     /* set a callback for the next 32-scanline increment */
  207.     scanline += 32;
  208.     if (scanline >= 256) scanline = 0;
  209.     irscanline_timer = timer_set(cpu_getscanlinetime(scanline), scanline, scanline_callback);
  210. }
  211.  
  212. void irobot_init_machine(void)
  213. {
  214.     UINT8 *MB = memory_region(REGION_CPU2);
  215.  
  216.     /* initialize the memory regions */
  217.     mbROM         = MB + 0x00000;
  218.     mbRAM         = MB + 0x0c000;
  219.     comRAM[0]    = MB + 0x0e000;
  220.     comRAM[1]    = MB + 0x0f000;
  221.  
  222.     irvg_vblank=0;
  223.     irvg_running = 0;
  224.     irmb_running = 0;
  225.  
  226.     /* set an initial timer to go off on scanline 0 */
  227.     irscanline_timer = timer_set(cpu_getscanlinetime(0), 0, scanline_callback);
  228.  
  229.     irobot_rom_banksel_w(0,0);
  230.     irobot_out0_w(0,0);
  231.     irobot_combase = comRAM[0];
  232.     irobot_combase_mb = comRAM[1];
  233.     irobot_outx = 0;
  234. }
  235.  
  236. WRITE_HANDLER( irobot_control_w )
  237. {
  238.  
  239.     irobot_control_num = offset & 0x03;
  240. }
  241.  
  242. READ_HANDLER( irobot_control_r )
  243. {
  244.  
  245.     if (irobot_control_num == 0)
  246.         return readinputport (5);
  247.     else if (irobot_control_num == 1)
  248.         return readinputport (6);
  249.     return 0;
  250.  
  251. }
  252.  
  253. /*  we allow irmb_running and irvg_running to appear running before clearing
  254.     them to simulate the mathbox and vector generator running in real time */
  255. READ_HANDLER( irobot_status_r )
  256. {
  257.     int d=0;
  258.  
  259.     logerror("status read. ");
  260.     IR_CPU_STATE;
  261.  
  262.     if (!irmb_running) d |= 0x20;
  263.     if (irvg_running) d |= 0x40;
  264.  
  265.     //        d = (irmb_running * 0x20) | (irvg_running * 0x40);
  266.     if (irvg_vblank) d = d | 0x80;
  267. #if IR_TIMING
  268.     /* flags are cleared by callbacks */
  269. #else
  270.     irmb_running=0;
  271.     irvg_running=0;
  272. #endif
  273.     return d;
  274. }
  275.  
  276.  
  277. /***********************************************************************
  278.  
  279.     I-Robot Mathbox
  280.  
  281.     Based on 4 2901 chips slice processors connected to form a 16-bit ALU
  282.  
  283.     Microcode roms:
  284.     6N: bits 0..3: Address of ALU A register
  285.     5P: bits 0..3: Address of ALU B register
  286.     6M: bits 0..3: ALU Function bits 5..8
  287.     7N: bits 0..3: ALU Function bits 1..4
  288.     8N: bits 0,1: Memory write timing
  289.         bit 2: Hardware multiply mode
  290.         bit 3: ALU Function bit 0
  291.     6P: bits 0,1: Direct addressing bits 0,1
  292.         bits 2,3: Jump address bits 0,1
  293.     8M: bits 0..3: Jump address bits 6..9
  294.     9N: bits 0..3: Jump address bits 2..5
  295.     8P: bits 0..3: Memory address bits 2..5
  296.     9M: bit 0: Shift control
  297.         bits 1..3: Jump type
  298.             0 = No Jump
  299.             1 = On carry
  300.             2 = On zero
  301.             3 = On positive
  302.             4 = On negative
  303.             5 = Unconditional
  304.             6 = Jump to Subroutine
  305.             7 = Return from Subroutine
  306.     7M: Bit 0: Mathbox memory enable
  307.         Bit 1: Latch data to address bus
  308.         Bit 2: Carry in select
  309.         Bit 3: Carry in value
  310.         (if 2,3 = 11 then mathbox is done)
  311.     9P: Bit 0: Hardware divide enable
  312.         Bits 1,2: Memory select
  313.         Bit 3: Memory R/W
  314.     7P: Bits 0,1: Direct addressing bits 6,7
  315.         Bits 2,3: Unused
  316.  
  317. ***********************************************************************/
  318.  
  319. #define FL_MULT    0x01
  320. #define FL_shift 0x02
  321. #define FL_MBMEMDEC 0x04
  322. #define FL_ADDEN 0x08
  323. #define FL_DPSEL 0x10
  324. #define FL_carry 0x20
  325. #define FL_DIV 0x40
  326. #define FL_MBRW 0x80
  327.  
  328. typedef struct irmb_ops
  329. {
  330.     const struct irmb_ops *nxtop;
  331.     UINT32 func;
  332.     UINT32 diradd;
  333.     UINT32 latchmask;
  334.     UINT32 *areg;
  335.     UINT32 *breg;
  336.     UINT8 cycles;
  337.     UINT8 diren;
  338.     UINT8 flags;
  339.     UINT8 ramsel;
  340. } irmb_ops;
  341.  
  342. static irmb_ops *mbops;
  343.  
  344. static const irmb_ops *irmb_stack[16];
  345. static UINT32 irmb_regs[16];
  346. static UINT32 irmb_latch;
  347.  
  348. #if DISASSEMBLE_MB_ROM
  349. void disassemble_instruction(irmb_ops *op);
  350. #endif
  351.  
  352.  
  353. UINT32 irmb_din(const irmb_ops *curop)
  354. {
  355.     UINT32 d = 0;
  356.  
  357.     if (!(curop->flags & FL_MBMEMDEC) && (curop->flags & FL_MBRW))
  358.     {
  359.         UINT32 ad = curop->diradd | (irmb_latch & curop->latchmask);
  360.  
  361.         if (curop->diren || (irmb_latch & 0x6000) == 0)
  362.             d = READ_WORD(&mbRAM[(ad << 1) & 0x1fff]);        /* MB RAM read */
  363.         else if (irmb_latch & 0x4000)
  364.             d = READ_WORD(&mbROM[(ad << 1) + 0x4000]);        /* MB ROM read, CEMATH = 1 */
  365.         else
  366.             d = READ_WORD(&mbROM[(ad << 1) & 0x3fff]);        /* MB ROM read, CEMATH = 0 */
  367.     }
  368.     return d;
  369. }
  370.  
  371.  
  372. void irmb_dout(const irmb_ops *curop, UINT32 d)
  373. {
  374.     /* Write to video com ram */
  375.     if (curop->ramsel == 3)
  376.         WRITE_WORD(&irobot_combase_mb[(irmb_latch << 1) & 0xfff], d);
  377.  
  378.     /* Write to mathox ram */
  379.     if (!(curop->flags & FL_MBMEMDEC))
  380.     {
  381.         UINT32 ad = curop->diradd | (irmb_latch & curop->latchmask);
  382.  
  383.         if (curop->diren || (irmb_latch & 0x6000) == 0)
  384.             WRITE_WORD(&mbRAM[(ad << 1) & 0x1fff], d);        /* MB RAM write */
  385.     }
  386. }
  387.  
  388.  
  389. /* Convert microcode roms to a more usable form */
  390. void load_oproms(void)
  391. {
  392.     UINT8 *MB = memory_region(REGION_CPU2);
  393.     int i;
  394.  
  395.     /* allocate RAM */
  396.     mbops = malloc(sizeof(irmb_ops) * 1024);
  397.     if (!mbops) return;
  398.  
  399.     for (i = 0; i < 1024; i++)
  400.     {
  401.         int nxtadd, func, ramsel, diradd, latchmask, dirmask, time;
  402.  
  403.         mbops[i].areg = &irmb_regs[MB[0xC000 + i] & 0x0F];
  404.         mbops[i].breg = &irmb_regs[MB[0xC400 + i] & 0x0F];
  405.         func = (MB[0xC800 + i] & 0x0F) << 5;
  406.         func |= ((MB[0xCC00 +i] & 0x0F) << 1);
  407.         func |= (MB[0xD000 + i] & 0x08) >> 3;
  408.         time = MB[0xD000 + i] & 0x03;
  409.         mbops[i].flags = (MB[0xD000 + i] & 0x04) >> 2;
  410.         nxtadd = (MB[0xD400 + i] & 0x0C) >> 2;
  411.         diradd = MB[0xD400 + i] & 0x03;
  412.         nxtadd |= ((MB[0xD800 + i] & 0x0F) << 6);
  413.         nxtadd |= ((MB[0xDC00 + i] & 0x0F) << 2);
  414.         diradd |= (MB[0xE000 + i] & 0x0F) << 2;
  415.         func |= (MB[0xE400 + i] & 0x0E) << 9;
  416.         mbops[i].flags |= (MB[0xE400 + i] & 0x01) << 1;
  417.         mbops[i].flags |= (MB[0xE800 + i] & 0x0F) << 2;
  418.         mbops[i].flags |= ((MB[0xEC00 + i] & 0x01) << 6);
  419.         mbops[i].flags |= (MB[0xEC00 + i] & 0x08) << 4;
  420.         ramsel = (MB[0xEC00 + i] & 0x06) >> 1;
  421.         diradd |= (MB[0xF000 + i] & 0x03) << 6;
  422.  
  423.         if (mbops[i].flags & FL_shift) func |= 0x200;
  424.  
  425.         mbops[i].func = func;
  426.         mbops[i].nxtop = &mbops[nxtadd];
  427.  
  428.         /* determine the number of 12MHz cycles for this operation */
  429.         if (time == 3)
  430.             mbops[i].cycles = 2;
  431.         else
  432.             mbops[i].cycles = 3 + time;
  433.  
  434.         /* precompute the hardcoded address bits and the mask to be used on the latch value */
  435.         if (ramsel == 0)
  436.         {
  437.             dirmask = 0x00FC;
  438.             latchmask = 0x3000;
  439.         }
  440.         else
  441.         {
  442.             dirmask = 0x0000;
  443.             latchmask = 0x3FFC;
  444.         }
  445.         if (ramsel & 2)
  446.             latchmask |= 0x0003;
  447.         else
  448.             dirmask |= 0x0003;
  449.  
  450.         mbops[i].ramsel = ramsel;
  451.         mbops[i].diradd = diradd & dirmask;
  452.         mbops[i].latchmask = latchmask;
  453.         mbops[i].diren = (ramsel == 0);
  454.  
  455. #if DISASSEMBLE_MB_ROM
  456.         disassemble_instruction(&mbops[i]);
  457. #endif
  458.     }
  459. }
  460.  
  461.  
  462. /* Init mathbox (only called once) */
  463. void init_irobot(void)
  464. {
  465.     int i;
  466.     for (i = 0; i < 16; i++)
  467.     {
  468.         irmb_stack[i] = &mbops[0];
  469.         irmb_regs[i] = 0;
  470.     }
  471.     irmb_latch=0;
  472.     load_oproms();
  473. }
  474.  
  475. static void irmb_done_callback (int param)
  476. {
  477.     logerror("mb done. ");
  478.     IR_CPU_STATE;
  479.     irmb_running = 0;
  480.     cpu_set_irq_line(0, M6809_FIRQ_LINE, ASSERT_LINE);
  481. }
  482.  
  483.  
  484. #define COMPUTE_CI \
  485.     CI = 0;\
  486.     if (curop->flags & FL_DPSEL)\
  487.         CI = cflag;\
  488.     else\
  489.     {\
  490.         if (curop->flags & FL_carry)\
  491.             CI = 1;\
  492.         if (!(prevop->flags & FL_DIV) && !nflag)\
  493.             CI = 1;\
  494.     }
  495.  
  496. #define ADD(r,s) \
  497.     COMPUTE_CI;\
  498.     result = r + s + CI;\
  499.     cflag = (result >> 16) & 1;\
  500.     vflag = (((r & 0x7fff) + (s & 0x7fff) + CI) >> 15) ^ cflag
  501.  
  502. #define SUBR(r,s) \
  503.     COMPUTE_CI;\
  504.     result = (r ^ 0xFFFF) + s + CI;         /*S - R + CI - 1*/ \
  505.     cflag = (result >> 16) & 1;\
  506.     vflag = (((s & 0x7fff) + ((r ^ 0xffff) & 0x7fff) + CI) >> 15) ^ cflag
  507.  
  508. #define SUB(r,s) \
  509.     COMPUTE_CI;\
  510.     result = r + (s ^ 0xFFFF) + CI;      /*R - S + CI - 1*/ \
  511.     cflag = (result >> 16) & 1;\
  512.     vflag = (((r & 0x7fff) + ((s ^ 0xffff) & 0x7fff) + CI) >> 15) ^ cflag
  513.  
  514. #define OR(r,s) \
  515.     result = r | s;\
  516.     vflag = cflag = 0
  517.  
  518. #define AND(r,s) \
  519.     result = r & s;\
  520.     vflag = cflag = 0
  521.  
  522. #define IAND(r,s) \
  523.     result = (r ^ 0xFFFF) & s;\
  524.     vflag = cflag = 0
  525.  
  526. #define XOR(r,s) \
  527.     result = r ^ s;\
  528.     vflag = cflag = 0
  529.  
  530. #define IXOR(r,s) \
  531.     result = (r ^ s) ^ 0xFFFF;\
  532.     vflag = cflag = 0
  533.  
  534.  
  535. #define DEST0 \
  536.     Q = Y = zresult
  537.  
  538. #define DEST1 \
  539.     Y = zresult
  540.  
  541. #define DEST2 \
  542.     Y = *curop->areg;\
  543.     *curop->breg = zresult
  544.  
  545. #define DEST3 \
  546.     *curop->breg = zresult;\
  547.     Y = zresult
  548.  
  549. #define DEST4_NOSHIFT \
  550.     *curop->breg = (zresult >> 1) | ((curop->flags & 0x20) << 10);\
  551.     Q = (Q >> 1) | ((curop->flags & 0x20) << 10);\
  552.     Y = zresult
  553.  
  554. #define DEST4_SHIFT \
  555.     *curop->breg = (zresult >> 1) | ((nflag ^ vflag) << 15);\
  556.     Q = (Q >> 1) | ((zresult & 0x01) << 15);\
  557.     Y = zresult
  558.  
  559. #define DEST5_NOSHIFT \
  560.     *curop->breg = (zresult >> 1) | ((curop->flags & 0x20) << 10);\
  561.     Y = zresult
  562.  
  563. #define DEST5_SHIFT \
  564.     *curop->breg = (zresult >> 1) | ((nflag ^ vflag) << 15);\
  565.     Y = zresult
  566.  
  567. #define DEST6_NOSHIFT \
  568.     *curop->breg = zresult << 1;\
  569.     Q = ((Q << 1) & 0xffff) | (nflag ^ 1);\
  570.     Y = zresult
  571.  
  572. #define DEST6_SHIFT \
  573.     *curop->breg = (zresult << 1) | ((Q & 0x8000) >> 15);\
  574.     Q = (Q << 1) & 0xffff;\
  575.     Y = zresult
  576.  
  577. #define DEST7_NOSHIFT \
  578.     *curop->breg = zresult << 1;\
  579.     Y = zresult
  580.  
  581. #define DEST7_SHIFT \
  582.     *curop->breg = (zresult << 1) | ((Q & 0x8000) >> 15);\
  583.     Y = zresult
  584.  
  585.  
  586. #define JUMP0     curop++;
  587. #define JUMP1    if (cflag) curop = curop->nxtop; else curop++;
  588. #define JUMP2    if (!zresult) curop = curop->nxtop; else curop++;
  589. #define JUMP3    if (!nflag) curop = curop->nxtop; else curop++;
  590. #define JUMP4    if (nflag) curop = curop->nxtop; else curop++;
  591. #define JUMP5    curop = curop->nxtop;
  592. #define JUMP6    irmb_stack[SP] = curop + 1; SP = (SP + 1) & 15; curop = curop->nxtop;
  593. #define JUMP7    SP = (SP - 1) & 15; curop = irmb_stack[SP];
  594.  
  595.  
  596. /* Run mathbox */
  597. void irmb_run(void)
  598. {
  599.     const irmb_ops *prevop = &mbops[0];
  600.     const irmb_ops *curop = &mbops[0];
  601.  
  602.     UINT32 Q = 0;
  603.     UINT32 Y = 0;
  604.     UINT32 nflag = 0;
  605.     UINT32 vflag = 0;
  606.     UINT32 cflag = 0;
  607.     UINT32 zresult = 1;
  608.     UINT32 CI = 0;
  609.     UINT32 SP = 0;
  610.     UINT32 icount = 0;
  611.  
  612.     profiler_mark(PROFILER_USER1);
  613.  
  614.     while ((prevop->flags & (FL_DPSEL | FL_carry)) != (FL_DPSEL | FL_carry))
  615.     {
  616.         UINT32 result;
  617.         UINT32 fu;
  618.         UINT32 tmp;
  619.  
  620.         icount += curop->cycles;
  621.  
  622.         /* Get function code */
  623.         fu = curop->func;
  624.  
  625.         /* Modify function for MULT */
  626.         if (!(prevop->flags & FL_MULT) || (Q & 1))
  627.             fu = fu ^ 0x02;
  628.         else
  629.             fu = fu | 0x02;
  630.  
  631.         /* Modify function for DIV */
  632.         if ((prevop->flags & FL_DIV) || nflag)
  633.             fu = fu ^ 0x08;
  634.         else
  635.             fu = fu | 0x08;
  636.  
  637.         /* Do source and operation */
  638.         switch (fu & 0x03f)
  639.         {
  640.             case 0x00:    ADD(*curop->areg, Q);                                break;
  641.             case 0x01:    ADD(*curop->areg, *curop->breg);                    break;
  642.             case 0x02:    ADD(0, Q);                                            break;
  643.             case 0x03:    ADD(0, *curop->breg);                                break;
  644.             case 0x04:    ADD(0, *curop->areg);                                break;
  645.             case 0x05:    tmp = irmb_din(curop); ADD(tmp, *curop->areg);        break;
  646.             case 0x06:    tmp = irmb_din(curop); ADD(tmp, Q);                    break;
  647.             case 0x07:    tmp = irmb_din(curop); ADD(tmp, 0);                    break;
  648.             case 0x08:    SUBR(*curop->areg, Q);                                break;
  649.             case 0x09:    SUBR(*curop->areg, *curop->breg);                    break;
  650.             case 0x0a:    SUBR(0, Q);                                            break;
  651.             case 0x0b:    SUBR(0, *curop->breg);                                break;
  652.             case 0x0c:    SUBR(0, *curop->areg);                                break;
  653.             case 0x0d:    tmp = irmb_din(curop); SUBR(tmp, *curop->areg);        break;
  654.             case 0x0e:    tmp = irmb_din(curop); SUBR(tmp, Q);                break;
  655.             case 0x0f:    tmp = irmb_din(curop); SUBR(tmp, 0);                break;
  656.             case 0x10:    SUB(*curop->areg, Q);                                break;
  657.             case 0x11:    SUB(*curop->areg, *curop->breg);                    break;
  658.             case 0x12:    SUB(0, Q);                                            break;
  659.             case 0x13:    SUB(0, *curop->breg);                                break;
  660.             case 0x14:    SUB(0, *curop->areg);                                break;
  661.             case 0x15:    tmp = irmb_din(curop); SUB(tmp, *curop->areg);        break;
  662.             case 0x16:    tmp = irmb_din(curop); SUB(tmp, Q);                    break;
  663.             case 0x17:    tmp = irmb_din(curop); SUB(tmp, 0);                    break;
  664.             case 0x18:    OR(*curop->areg, Q);                                break;
  665.             case 0x19:    OR(*curop->areg, *curop->breg);                        break;
  666.             case 0x1a:    OR(0, Q);                                            break;
  667.             case 0x1b:    OR(0, *curop->breg);                                break;
  668.             case 0x1c:    OR(0, *curop->areg);                                break;
  669.             case 0x1d:    OR(irmb_din(curop), *curop->areg);                    break;
  670.             case 0x1e:    OR(irmb_din(curop), Q);                                break;
  671.             case 0x1f:    OR(irmb_din(curop), 0);                                break;
  672.             case 0x20:    AND(*curop->areg, Q);                                break;
  673.             case 0x21:    AND(*curop->areg, *curop->breg);                    break;
  674.             case 0x22:    AND(0, Q);                                            break;
  675.             case 0x23:    AND(0, *curop->breg);                                break;
  676.             case 0x24:    AND(0, *curop->areg);                                break;
  677.             case 0x25:    AND(irmb_din(curop), *curop->areg);                    break;
  678.             case 0x26:    AND(irmb_din(curop), Q);                            break;
  679.             case 0x27:    AND(irmb_din(curop), 0);                            break;
  680.             case 0x28:    IAND(*curop->areg, Q);                                break;
  681.             case 0x29:    IAND(*curop->areg, *curop->breg);                    break;
  682.             case 0x2a:    IAND(0, Q);                                            break;
  683.             case 0x2b:    IAND(0, *curop->breg);                                break;
  684.             case 0x2c:    IAND(0, *curop->areg);                                break;
  685.             case 0x2d:    IAND(irmb_din(curop), *curop->areg);                break;
  686.             case 0x2e:    IAND(irmb_din(curop), Q);                            break;
  687.             case 0x2f:    IAND(irmb_din(curop), 0);                            break;
  688.             case 0x30:    XOR(*curop->areg, Q);                                break;
  689.             case 0x31:    XOR(*curop->areg, *curop->breg);                    break;
  690.             case 0x32:    XOR(0, Q);                                            break;
  691.             case 0x33:    XOR(0, *curop->breg);                                break;
  692.             case 0x34:    XOR(0, *curop->areg);                                break;
  693.             case 0x35:    XOR(irmb_din(curop), *curop->areg);                    break;
  694.             case 0x36:    XOR(irmb_din(curop), Q);                            break;
  695.             case 0x37:    XOR(irmb_din(curop), 0);                            break;
  696.             case 0x38:    IXOR(*curop->areg, Q);                                break;
  697.             case 0x39:    IXOR(*curop->areg, *curop->breg);                    break;
  698.             case 0x3a:    IXOR(0, Q);                                            break;
  699.             case 0x3b:    IXOR(0, *curop->breg);                                break;
  700.             case 0x3c:    IXOR(0, *curop->areg);                                break;
  701.             case 0x3d:    IXOR(irmb_din(curop), *curop->areg);                break;
  702.             case 0x3e:    IXOR(irmb_din(curop), Q);                            break;
  703. default:    case 0x3f:    IXOR(irmb_din(curop), 0);                            break;
  704.         }
  705.  
  706.         /* Evaluate flags */
  707.         zresult = result & 0xFFFF;
  708.         nflag = zresult >> 15;
  709.  
  710.         prevop = curop;
  711.  
  712.         /* Do destination and jump */
  713.         switch (fu >> 6)
  714.         {
  715.             case 0x00:
  716.             case 0x08:    DEST0;            JUMP0;    break;
  717.             case 0x01:
  718.             case 0x09:    DEST1;            JUMP0;    break;
  719.             case 0x02:
  720.             case 0x0a:    DEST2;            JUMP0;    break;
  721.             case 0x03:
  722.             case 0x0b:    DEST3;            JUMP0;    break;
  723.             case 0x04:    DEST4_NOSHIFT;    JUMP0;    break;
  724.             case 0x05:    DEST5_NOSHIFT;    JUMP0;    break;
  725.             case 0x06:    DEST6_NOSHIFT;    JUMP0;    break;
  726.             case 0x07:    DEST7_NOSHIFT;    JUMP0;    break;
  727.             case 0x0c:    DEST4_SHIFT;    JUMP0;    break;
  728.             case 0x0d:    DEST5_SHIFT;    JUMP0;    break;
  729.             case 0x0e:    DEST6_SHIFT;    JUMP0;    break;
  730.             case 0x0f:    DEST7_SHIFT;    JUMP0;    break;
  731.  
  732.             case 0x10:
  733.             case 0x18:    DEST0;            JUMP1;    break;
  734.             case 0x11:
  735.             case 0x19:    DEST1;            JUMP1;    break;
  736.             case 0x12:
  737.             case 0x1a:    DEST2;            JUMP1;    break;
  738.             case 0x13:
  739.             case 0x1b:    DEST3;            JUMP1;    break;
  740.             case 0x14:    DEST4_NOSHIFT;    JUMP1;    break;
  741.             case 0x15:    DEST5_NOSHIFT;    JUMP1;    break;
  742.             case 0x16:    DEST6_NOSHIFT;    JUMP1;    break;
  743.             case 0x17:    DEST7_NOSHIFT;    JUMP1;    break;
  744.             case 0x1c:    DEST4_SHIFT;    JUMP1;    break;
  745.             case 0x1d:    DEST5_SHIFT;    JUMP1;    break;
  746.             case 0x1e:    DEST6_SHIFT;    JUMP1;    break;
  747.             case 0x1f:    DEST7_SHIFT;    JUMP1;    break;
  748.  
  749.             case 0x20:
  750.             case 0x28:    DEST0;            JUMP2;    break;
  751.             case 0x21:
  752.             case 0x29:    DEST1;            JUMP2;    break;
  753.             case 0x22:
  754.             case 0x2a:    DEST2;            JUMP2;    break;
  755.             case 0x23:
  756.             case 0x2b:    DEST3;            JUMP2;    break;
  757.             case 0x24:    DEST4_NOSHIFT;    JUMP2;    break;
  758.             case 0x25:    DEST5_NOSHIFT;    JUMP2;    break;
  759.             case 0x26:    DEST6_NOSHIFT;    JUMP2;    break;
  760.             case 0x27:    DEST7_NOSHIFT;    JUMP2;    break;
  761.             case 0x2c:    DEST4_SHIFT;    JUMP2;    break;
  762.             case 0x2d:    DEST5_SHIFT;    JUMP2;    break;
  763.             case 0x2e:    DEST6_SHIFT;    JUMP2;    break;
  764.             case 0x2f:    DEST7_SHIFT;    JUMP2;    break;
  765.  
  766.             case 0x30:
  767.             case 0x38:    DEST0;            JUMP3;    break;
  768.             case 0x31:
  769.             case 0x39:    DEST1;            JUMP3;    break;
  770.             case 0x32:
  771.             case 0x3a:    DEST2;            JUMP3;    break;
  772.             case 0x33:
  773.             case 0x3b:    DEST3;            JUMP3;    break;
  774.             case 0x34:    DEST4_NOSHIFT;    JUMP3;    break;
  775.             case 0x35:    DEST5_NOSHIFT;    JUMP3;    break;
  776.             case 0x36:    DEST6_NOSHIFT;    JUMP3;    break;
  777.             case 0x37:    DEST7_NOSHIFT;    JUMP3;    break;
  778.             case 0x3c:    DEST4_SHIFT;    JUMP3;    break;
  779.             case 0x3d:    DEST5_SHIFT;    JUMP3;    break;
  780.             case 0x3e:    DEST6_SHIFT;    JUMP3;    break;
  781.             case 0x3f:    DEST7_SHIFT;    JUMP3;    break;
  782.  
  783.             case 0x40:
  784.             case 0x48:    DEST0;            JUMP4;    break;
  785.             case 0x41:
  786.             case 0x49:    DEST1;            JUMP4;    break;
  787.             case 0x42:
  788.             case 0x4a:    DEST2;            JUMP4;    break;
  789.             case 0x43:
  790.             case 0x4b:    DEST3;            JUMP4;    break;
  791.             case 0x44:    DEST4_NOSHIFT;    JUMP4;    break;
  792.             case 0x45:    DEST5_NOSHIFT;    JUMP4;    break;
  793.             case 0x46:    DEST6_NOSHIFT;    JUMP4;    break;
  794.             case 0x47:    DEST7_NOSHIFT;    JUMP4;    break;
  795.             case 0x4c:    DEST4_SHIFT;    JUMP4;    break;
  796.             case 0x4d:    DEST5_SHIFT;    JUMP4;    break;
  797.             case 0x4e:    DEST6_SHIFT;    JUMP4;    break;
  798.             case 0x4f:    DEST7_SHIFT;    JUMP4;    break;
  799.  
  800.             case 0x50:
  801.             case 0x58:    DEST0;            JUMP5;    break;
  802.             case 0x51:
  803.             case 0x59:    DEST1;            JUMP5;    break;
  804.             case 0x52:
  805.             case 0x5a:    DEST2;            JUMP5;    break;
  806.             case 0x53:
  807.             case 0x5b:    DEST3;            JUMP5;    break;
  808.             case 0x54:    DEST4_NOSHIFT;    JUMP5;    break;
  809.             case 0x55:    DEST5_NOSHIFT;    JUMP5;    break;
  810.             case 0x56:    DEST6_NOSHIFT;    JUMP5;    break;
  811.             case 0x57:    DEST7_NOSHIFT;    JUMP5;    break;
  812.             case 0x5c:    DEST4_SHIFT;    JUMP5;    break;
  813.             case 0x5d:    DEST5_SHIFT;    JUMP5;    break;
  814.             case 0x5e:    DEST6_SHIFT;    JUMP5;    break;
  815.             case 0x5f:    DEST7_SHIFT;    JUMP5;    break;
  816.  
  817.             case 0x60:
  818.             case 0x68:    DEST0;            JUMP6;    break;
  819.             case 0x61:
  820.             case 0x69:    DEST1;            JUMP6;    break;
  821.             case 0x62:
  822.             case 0x6a:    DEST2;            JUMP6;    break;
  823.             case 0x63:
  824.             case 0x6b:    DEST3;            JUMP6;    break;
  825.             case 0x64:    DEST4_NOSHIFT;    JUMP6;    break;
  826.             case 0x65:    DEST5_NOSHIFT;    JUMP6;    break;
  827.             case 0x66:    DEST6_NOSHIFT;    JUMP6;    break;
  828.             case 0x67:    DEST7_NOSHIFT;    JUMP6;    break;
  829.             case 0x6c:    DEST4_SHIFT;    JUMP6;    break;
  830.             case 0x6d:    DEST5_SHIFT;    JUMP6;    break;
  831.             case 0x6e:    DEST6_SHIFT;    JUMP6;    break;
  832.             case 0x6f:    DEST7_SHIFT;    JUMP6;    break;
  833.  
  834.             case 0x70:
  835.             case 0x78:    DEST0;            JUMP7;    break;
  836.             case 0x71:
  837.             case 0x79:    DEST1;            JUMP7;    break;
  838.             case 0x72:
  839.             case 0x7a:    DEST2;            JUMP7;    break;
  840.             case 0x73:
  841.             case 0x7b:    DEST3;            JUMP7;    break;
  842.             case 0x74:    DEST4_NOSHIFT;    JUMP7;    break;
  843.             case 0x75:    DEST5_NOSHIFT;    JUMP7;    break;
  844.             case 0x76:    DEST6_NOSHIFT;    JUMP7;    break;
  845.             case 0x77:    DEST7_NOSHIFT;    JUMP7;    break;
  846.             case 0x7c:    DEST4_SHIFT;    JUMP7;    break;
  847.             case 0x7d:    DEST5_SHIFT;    JUMP7;    break;
  848.             case 0x7e:    DEST6_SHIFT;    JUMP7;    break;
  849.             case 0x7f:    DEST7_SHIFT;    JUMP7;    break;
  850.         }
  851.  
  852.         /* Do write */
  853.         if (!(prevop->flags & FL_MBRW))
  854.             irmb_dout(prevop, Y);
  855.  
  856.         /* ADDEN */
  857.         if (!(prevop->flags & FL_ADDEN))
  858.         {
  859.             if (prevop->flags & FL_MBRW)
  860.                 irmb_latch = irmb_din(prevop);
  861.             else
  862.                 irmb_latch = Y;
  863.         }
  864.     }
  865.     profiler_mark(PROFILER_END);
  866.  
  867.     logerror("%d instructions for Mathbox \n", icount);
  868.  
  869.  
  870. #if IR_TIMING
  871.     if (irmb_running == 0)
  872.     {
  873.         irmb_timer = timer_set (TIME_IN_HZ(12000000) * icount, 0, irmb_done_callback);
  874.         logerror("mb start ");
  875.         IR_CPU_STATE;
  876.     }
  877.     else
  878.     {
  879.         logerror("mb start [busy!] ");
  880.         IR_CPU_STATE;
  881.         timer_reset (irmb_timer, TIME_IN_NSEC(200) * icount);
  882.     }
  883. #else
  884.     cpu_set_irq_line(0, M6809_FIRQ_LINE, ASSERT_LINE);
  885. #endif
  886.     irmb_running=1;
  887. }
  888.  
  889.  
  890.  
  891.  
  892. #if DISASSEMBLE_MB_ROM
  893. void disassemble_instruction(irmb_ops *op)
  894. {
  895.     int lp;
  896.  
  897.     if (i==0)
  898.         logerror(" Address  a b func stor: Q :Y, R, S RDCSAESM da m rs\n");
  899.     logerror("%04X    : ",i);
  900.     logerror("%X ",op->areg);
  901.     logerror("%X ",op->breg);
  902.  
  903.     lp=(op->func & 0x38)>>3;
  904.     if ((lp&1)==0)
  905.         lp|=1;
  906.     else if((op->flags & FL_DIV) != 0)
  907.         lp&=6;
  908.     else
  909.         logerror("*");
  910.  
  911.     switch (lp)
  912.     {
  913.         case 0:
  914.             logerror("ADD  ");
  915.             break;
  916.         case 1:
  917.             logerror("SUBR ");
  918.             break;
  919.         case 2:
  920.             logerror("SUB  ");
  921.             break;
  922.         case 3:
  923.             logerror("OR   ");
  924.             break;
  925.         case 4:
  926.             logerror("AND  ");
  927.             break;
  928.         case 5:
  929.             logerror("AND  ");
  930.             break;
  931.         case 6:
  932.             logerror("XOR  ");
  933.             break;
  934.         case 7:
  935.             logerror("XNOR ");
  936.             break;
  937.     }
  938.  
  939.     switch ((op->func & 0x1c0)>>6)
  940.     {
  941.         case 0:
  942.             logerror("  - : Q :F,");
  943.             break;
  944.         case 1:
  945.             logerror("  - : - :F,");
  946.             break;
  947.         case 2:
  948.             logerror("  R%x: - :A,",op->breg);
  949.             break;
  950.         case 3:
  951.             logerror("  R%x: - :F,",op->breg);
  952.             break;
  953.         case 4:
  954.             logerror(">>R%x:>>Q:F,",op->breg);
  955.             break;
  956.         case 5:
  957.             logerror(">>R%x: - :F,",op->breg);
  958.             break;
  959.         case 6:
  960.             logerror("<<R%x:<<Q:F,",op->breg);
  961.             break;
  962.         case 7:
  963.             logerror("<<R%x: - :F,",op->breg);
  964.             break;
  965.     }
  966.  
  967.     lp=(op->func & 0x7);
  968.     if ((lp&2)==0)
  969.         lp|=2;
  970.     else if((op->flags & FL_MULT) == 0)
  971.         lp&=5;
  972.     else
  973.         logerror("*");
  974.  
  975.     switch (lp)
  976.     {
  977.         case 0:
  978.             logerror("R%x, Q ",op->areg);
  979.             break;
  980.         case 1:
  981.             logerror("R%x,R%x ",op->areg,op->breg);
  982.             break;
  983.         case 2:
  984.             logerror("00, Q ");
  985.             break;
  986.         case 3:
  987.             logerror("00,R%x ",op->breg);
  988.             break;
  989.         case 4:
  990.             logerror("00,R%x ",op->areg);
  991.             break;
  992.         case 5:
  993.             logerror(" D,R%x ",op->areg);
  994.             break;
  995.         case 6:
  996.             logerror(" D, Q ");
  997.             break;
  998.         case 7:
  999.             logerror(" D,00 ");
  1000.             break;
  1001.     }
  1002.  
  1003.     for (lp=0;lp<8;lp++)
  1004.         if (op->flags & (0x80>>lp))
  1005.             logerror("1");
  1006.         else
  1007.             logerror("0");
  1008.  
  1009.     logerror(" %02X ",op->diradd);
  1010.     logerror("%X\n",op->ramsel);
  1011.     if (op->jtype)
  1012.     {
  1013.         logerror("              ");
  1014.         switch (op->jtype)
  1015.         {
  1016.             case 1:
  1017.                 logerror("BO ");
  1018.                 break;
  1019.             case 2:
  1020.                 logerror("BZ ");
  1021.                 break;
  1022.             case 3:
  1023.                 logerror("BH ");
  1024.                 break;
  1025.             case 4:
  1026.                 logerror("BL ");
  1027.                 break;
  1028.             case 5:
  1029.                 logerror("B  ");
  1030.                 break;
  1031.             case 6:
  1032.                 logerror("Cl ");
  1033.                 break;
  1034.             case 7:
  1035.                 logerror("Return\n\n");
  1036.                 break;
  1037.         }
  1038.         if (op->jtype != 7) logerror("  %04X    \n",op->nxtadd);
  1039.         if (op->jtype == 5) logerror("\n");
  1040.         }
  1041.     }
  1042. }
  1043. #endif
  1044.